package erwiki.ui.app.lifecycle;

import java.util.concurrent.atomic.AtomicBoolean;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.workbench.lifecycle.PostContextCreate;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.service.ApplicationContext;
import org.eclipse.rap.rwt.service.UISessionEvent;
import org.eclipse.rap.rwt.service.UIThreadListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import au.com.cybersearch2.controls.ControlFactory;
import au.com.cybersearch2.controls.ImageFactory;
import au.com.cybersearch2.controls.ResourceTools;
import au.com.cybersearch2.statusbar.StatusBar;
import erwiki.api.auth.ISessionMonitor;
import erwiki.api.core.Engine;
import erwiki.api.core.WikiSession;
import erwiki.api.rwc.context.internal.service.ContextProviderW;
import erwiki.api.rwc.context.internal.service.ServiceContextW;
import erwiki.ui.app.statusbar.ExampleStatusBar;
import jakarta.annotation.PreDestroy;
import jakarta.inject.Inject;

@SuppressWarnings("restriction")
public class ApplicationLifecycle {

	private static final Logger log = Logger.getLogger(ApplicationLifecycle.class);

	@Inject
	Engine engine;

	@Inject
	ISessionMonitor sessionMonitor;

	ImageFactory imageFactory;
	ExampleStatusBar exampleStatusBar;

	@PostContextCreate
	void postContextCreate(IEclipseContext workbenchContext) {
		log.debug("Application postContextCreate");
		addRWContext();
		addStatusBar(workbenchContext);
	}

	@PreDestroy
	void preDestroy(IEclipseContext workbenchContext) {
		removeRWContext();
	}

	/**
	 * Создает run-time Wiki-контекст для данного контекста (UI Tread) RAP.
	 */
	private void addRWContext() {
		HttpServletRequest request = RWT.getRequest();
		HttpServletResponse response = RWT.getResponse();
		WikiSession wikiSession = sessionMonitor.getWikiSession(request);
		ServiceContextW context = new ServiceContextW(engine, wikiSession, request, response);
		ContextProviderW.setContext(context);
	}

	/**
	 * Удаляет run-time Wiki-контекст для данного контекста (UI Tread) RAP.
	 */
	private void removeRWContext() {
		ContextProviderW.disposeContext();
	}

	/**
	 * Добавляет элементы StatusBar в модель E4.
	 * 
	 * @param workbenchContext
	 */
	private void addStatusBar(IEclipseContext workbenchContext) {
		workbenchContext.set(ResourceTools.class, new ResourceTools());
		workbenchContext.set(ControlFactory.class, new ControlFactory());
		workbenchContext.set(StatusBar.class, new StatusBar());

		// Install image and SWT widget factories
//        imageFactory.setResourceBundle(FrameworkUtil.getBundle(this.getClass()));
//        imageFactory.registerCustomFactory(new PresenceImageFactory());

		/*:FVK:2
		imageFactory = ContextInjectionFactory.make(ImageFactory.class, workbenchContext);
		workbenchContext.set(ImageFactory.class, imageFactory);
		*/

		exampleStatusBar = ContextInjectionFactory.make(ExampleStatusBar.class, workbenchContext);

		/*
		final Display display = Display.getCurrent();
		final Runnable runnable = new Runnable() {
			public void run() {
				UISession uiSession = RWT.getUISession(display);
				uiSession.exec(new Runnable() {
					public void run() {
						exampleStatusBar = ContextInjectionFactory.make(ExampleStatusBar.class, workbenchContext);
					}
				});
			}
		};
		new Thread(runnable).start();
		*/
	}

	//:FVK: - это ввод пароля... (был пример)
	boolean postContextCreate_(Display d) {
		/*TODO: :FVK:: этот код - пример. Удалить.
		UISession uiSession = RWT.getUISession();
		uiSession.getHttpSession().setMaxInactiveInterval(5);
		final String id = uiSession.getId();
		uiSession.addUISessionListener(new UISessionListener() {
			private static final long serialVersionUID = 1L;
		
			@Override
			public void beforeDestroy(UISessionEvent event) {
				System.err.println("Destroyed session " + id);
			}
		});
		
		/// Завершение приложения.
		ApplicationContext ctx = RWT.getApplicationContext();
		Object val = ctx.getAttribute("IS_LISTENED");
		if(!(val instanceof String attr && !attr.equals(":FVK:"))) {
			System.out.println("APP IS_LISTENED - attached.");
			ctx.setAttribute("IS_LISTENED", ":FVK:");
			ctx.addApplicationContextListener(new ApplicationContextListener() {			
				private static final long serialVersionUID = 1L;
				
				@Override
				public void beforeDestroy(ApplicationContextEvent event) {
					System.err.println("Destroyed RAP application.");
				}
			});
			
		}
		*/

		return true;
	}

	boolean login(Display d) {
		final AtomicBoolean rv = new AtomicBoolean(false);
		final Shell s = new Shell(d);
		s.setText("Login");
		s.setLayout(new GridLayout(2, false));

		{
			Label l = new Label(s, SWT.NONE);
			l.setText("Username");

			Text t = new Text(s, SWT.BORDER);
			t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		}

		{
			Label l = new Label(s, SWT.NONE);
			l.setText("Password");

			Text t = new Text(s, SWT.BORDER);
			t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		}

		{
			Composite buttonContainer = new Composite(s, SWT.NONE);
			buttonContainer.setLayout(new GridLayout(2, true));
			buttonContainer.setLayoutData(new GridData(SWT.TRAIL, SWT.CENTER, false, false, 2, 1));

			{
				Button btnAbort = new Button(buttonContainer, SWT.PUSH);
				btnAbort.setText("Abort");
				btnAbort.addSelectionListener(new SelectionAdapter() {
					private static final long serialVersionUID = 1L;

					@Override
					public void widgetSelected(SelectionEvent e) {
						rv.set(false);
						s.dispose();
					}
				});
			}

			{
				Button btnLogin = new Button(buttonContainer, SWT.PUSH);
				btnLogin.setText("Login");
				btnLogin.addSelectionListener(new SelectionAdapter() {
					private static final long serialVersionUID = 1L;

					@Override
					public void widgetSelected(SelectionEvent e) {
						rv.set(true);
						s.dispose();
					}
				});
			}
		}
		s.pack();
		s.setSize(300, s.getSize().y + 10);
		Rectangle bounds = d.getPrimaryMonitor().getBounds();

		Point size = s.getSize();
		s.setLocation(bounds.width / 2 - size.x / 2, bounds.height / 2 - size.y / 2);

		s.open();
		while (!s.isDisposed() && !d.isDisposed()) {
			if (!d.readAndDispatch()) {
				d.sleep();
			}
		}

		return rv.get();
	}

}
